package com.luxsoft.siipap.compras.model;


import java.math.BigDecimal;
import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.hibernate.annotations.Formula;
import org.hibernate.annotations.Type;
import org.hibernate.validator.NotNull;

import com.luxsoft.siipap.inventarios.model.Inventario;
import com.luxsoft.siipap.maquila.model.MovimientoConFlete;
import com.luxsoft.siipap.model.CantidadMonetaria;
import com.luxsoft.siipap.model.core.Proveedor;
import com.luxsoft.sw3.maquila.model.AnalisisDeFlete;


/**
 * Entrada unitaria de material al inventario por concepto de compra
 * 
 * La relacion entre {@link CompraDet} y {@link EntradaPorCompra} es One-To-Many
 * Solo hay q' conciderar que en la coleccion CompraDet.entradas las reglas de equals y hashCode
 * son las que se eredan de {@link Inventario}
 * 
 * @author Ruben Cancino
 *
 */
@Entity
@Table(name="SX_INVENTARIO_COM")
public class EntradaPorCompra extends Inventario implements MovimientoConFlete{
	
	
	@Formula("(select IFNULL(sum(a.CANTIDAD),0) FROM SX_CXP_ANALISISDET a where a.entrada_id=INVENTARIO_ID)")
	private Double analizado;
	
	
	
	@ManyToOne (optional=false
			,cascade={CascadeType.PERSIST,CascadeType.MERGE}
			,fetch=FetchType.EAGER)
	@JoinColumn (name="PROVEEDOR_ID", nullable=false, updatable=false)
	@NotNull
	private Proveedor proveedor;
	
	
	
	@ManyToOne(optional=true,fetch=FetchType.LAZY)
	@JoinColumn (name="RECEPCION_ID",nullable=true)		
	private RecepcionDeCompra recepcion;
	
	@ManyToOne(optional=true,cascade={CascadeType.MERGE,CascadeType.PERSIST})
	@JoinColumn (name="COMPRADET_ID",nullable=true)	
	private CompraUnitaria compraDet;
	
	@Column(name="COMS2_ID",unique=true)
	private Long coms2Id;
	
	@Transient
	private Date insertTime;
	
	
	
	public EntradaPorCompra(){
	}
	
	public Proveedor getProveedor() {
		return proveedor;
	}
	public void setProveedor(Proveedor proveedor) {
		this.proveedor = proveedor;
	}


	public Long getComs2Id() {
		return coms2Id;
	}
	
	public void setComs2Id(Long coms2Id) {
		this.coms2Id = coms2Id;
	}

	public CompraUnitaria getCompraDet() {
		return compraDet;
	}

	public void setCompraDet(CompraUnitaria compraDet) {
		this.compraDet = compraDet;
	}
	
	public double getSolicitado(){
		if(getCompraDet()==null)
			return 0d;
		else
			return getCompraDet().getSolicitado();
	}	
	
	public double getAnalizado(){
		if(analizado==null)
			analizado=0d;
    	return analizado;
    }
	
	public double getPendienteDeAnalisis(){
		return getCantidad()-getAnalizado();
	}
	
	

	@Override
	public String getTipoDocto() {
		return "COM";
	}
	
	/** Ajuste de impedancia entre SiipapWin y SW2 ***/
	
	@Column(name="REMISION_F")
	@Type(type="date")
	private Date fechaRemision;
	
	@Column(name="REMISION",length=20)
	public String  remision;
	
	@Column(name="COMPRA")
	private int compra;
	
	@Column(name="COMPRA_F")
	@Type(type="date")
	private Date fechaCompra;
	
	@Column(name="SUCCOM")
	private Integer sucursalCompra;

	public Date getFechaRemision() {
		return fechaRemision;
	}

	public void setFechaRemision(Date fechaRemision) {
		this.fechaRemision = fechaRemision;
	}

	public String getRemision() {
		return remision;
	}

	public void setRemision(String remision) {
		this.remision = remision;
	}

	public int getCompra() {
		return compra;
	}

	public void setCompra(int compra) {
		this.compra = compra;
	}

	public Date getFechaCompra() {
		return fechaCompra;
	}

	public void setFechaCompra(Date fechaCompra) {
		this.fechaCompra = fechaCompra;
	}

	public Integer getSucursalCompra() {
		return sucursalCompra;
	}

	public void setSucursalCompra(Integer sucursalCompra) {
		this.sucursalCompra = sucursalCompra;
	}

	public double getKilosEntrada(){
		return getProducto().getKilos()*(getCantidad()/getFactor());
	}
	
	public double getKilosAnalizados(){
		return getProducto().getKilos()*(getAnalizado()/getFactor());
	}

	public RecepcionDeCompra getRecepcion() {
		return recepcion;
	}

	public void setRecepcion(RecepcionDeCompra recepcion) {
		this.recepcion = recepcion;
	}
	
	public double getPendiente(){
		if(getCompraDet()!=null){
			double cantidad=getId()==null?getCantidad():0;
			return getSolicitado()-getCompraDet().getRecibido()-cantidad;
		}
		return 0;
	}
	
	public void setCantidad(double cantidad) {
		super.setCantidad(cantidad);
		updateInsertTime();
	}

	public Date getInsertTime() {
		return insertTime;
	}	

	private void updateInsertTime(){
		if(insertTime==null){
			try {
				Thread.sleep(65);
				insertTime=new Date(System.currentTimeMillis());
			} catch (Exception e) {}
		}
	}

	//@Column(name="COSTO_FLETE",nullable=false,scale=6,precision=16)
	@Transient
	private BigDecimal costoFlete=BigDecimal.ZERO;
	
	
	//@ManyToOne(optional=true) 
    //@JoinColumn(name="ANALISIS_FLETE_ID")
	@Transient
	private AnalisisDeFlete analisisFlete;
	
	public AnalisisDeFlete getAnalisisFlete() {
		return analisisFlete;
	}

	public void setAnalisisFlete(AnalisisDeFlete analisisFlete) {
		this.analisisFlete = analisisFlete;
	}

	public BigDecimal getCostoFlete() {
		return costoFlete;
	}

	public void setCostoFlete(BigDecimal costoFlete) {
		Object old=this.costoFlete;
		this.costoFlete = costoFlete;
		firePropertyChange("costoFlete", old, costoFlete);
	}
	
	public BigDecimal getImporteDelFlete(){
		BigDecimal imp=getCostoFlete().multiply(BigDecimal.valueOf(getCantidadEnUnidad()));
		return CantidadMonetaria.pesos(imp).amount();
	}
	
	@Column(name="CONTENEDOR")
    private String contenedor;
    
	@Column(name="PALLETS")
    private int pallets;
    
    @Column(name="TONELADAS_NETA", scale=6, precision=14)
    private BigDecimal toneladasNeta;
    
    @Column(name="TONELADAS_BRUTA", scale=6, precision=14)
    private BigDecimal toneladaBruta;
    
    @Formula(value="(select (( (A.ANCHO*A.LARGO*A.GRAMOS)/10000)* (CANTIDAD/FACTORU))/1000 FROM SX_PRODUCTOS A  where a.PRODUCTO_ID=PRODUCTO_ID)")
    private BigDecimal toneladaEstimada;
    
    @Column(name="FACTURA")
    private String factura;

    @Column(name="PRECIO_VENTA")
    private BigDecimal precioVenta;

	public String getContenedor() {
		return contenedor;
	}

	public void setContenedor(String contenedor) {
		this.contenedor = contenedor;
	}

	public int getPallets() {
		return pallets;
	}

	public void setPallets(int pallets) {
		this.pallets = pallets;
	}

	public BigDecimal getToneladasNeta() {
		if(toneladasNeta==null){
			toneladasNeta=BigDecimal.ZERO;
		}
		return toneladasNeta;
	}

	public void setToneladasNeta(BigDecimal toneladasNeta) {
		this.toneladasNeta = toneladasNeta;
	}

	public BigDecimal getToneladaBruta() {
		return toneladaBruta;
	}

	public void setToneladaBruta(BigDecimal toneladaBruta) {
		this.toneladaBruta = toneladaBruta;
	}

	public BigDecimal getToneladaEstimada() {
		return toneladaEstimada;
	}

	public void setToneladaEstimada(BigDecimal toneladaEstimada) {
		this.toneladaEstimada = toneladaEstimada;
	}

	public String getFactura() {
		return factura;
	}

	public void setFactura(String factura) {
		this.factura = factura;
	}
    
	public boolean equals(Object obj)
    {
        if(obj == null)
            return false;
        if(obj == this)
            return true;
        if(getClass() != obj.getClass())
        {
            return false;
        } else
        {
            EntradaPorCompra other = (EntradaPorCompra)obj;
            return (new EqualsBuilder())
            .append(getTipoDocto(), other.getTipoDocto())
            .append(getSucursal(), other.getSucursal())
            .append(getFecha(), other.getFecha())
            .append(getProducto(), other.getProducto())
            .append(getUnidad(), other.getUnidad())
            .append(getCantidad(), other.getCantidad())
            .append(getContenedor(), other.getContenedor())
            .isEquals();
        }
    }

    public int hashCode(){
        return (new HashCodeBuilder(17, 35))
        .append(getTipoDocto())
        .append(getSucursal())
        .append(getFecha())
        .append(getProducto())
        .append(getUnidad())
        .append(getCantidad())
        .append(getContenedor())
        .toHashCode();
    }

    public String toString()
    {
        return (new ToStringBuilder(this, ToStringStyle.SIMPLE_STYLE)).append(getId()).append(getSucursal()).append(getFecha()).append(getProducto()).append(getUnidad()).append(getCantidad()).append(getContenedor()).toString();
    }
    
    public boolean isFacturada(){
    	return StringUtils.isNotBlank(getFactura());
    }

	public BigDecimal getPrecioVenta() {
		return precioVenta;
	}

	public void setPrecioVenta(BigDecimal precioVenta) {
		this.precioVenta = precioVenta;
	}
    
}
